Review of 4 Django Social Auth apps

TL;DR: I tried out four different Django social authentication and registration packages. The only one that worked out of the box was django-allauth, though django-social-auth looks like it could be promising. django-allauth is the only one that supports username/password registration as well as social registration.

One of those silly little things that almost any modern web application needs is authentication. And with authentication comes usernames, passwords, perhaps email confirmations — the dreary routine. A lot of newer sites decide to offload the chore of authentication to third parties through OpenID, Facebook Connect, Google accounts, etc. This makes a lot of sense — but it’s onerous to code up your own connectors to all of these providers. It is the perfect job for a simple pluggable app that lets your web framework handle authentication.

The rails community has OmniAuth, a comprehensive, well used and well tested solution. But in the Django world, we have no less than four distinct authentication packages for this purpose, each of which has hundreds of Github followers, thousands of downloads, and relatively current commit histories:

(Django Packages grids I used to pick these: authentication and facebook-authentication)

I did not include the venerable and relatively canonical django-registration here because it only ships with username/password registration, and not social registration.

My requirements:

  • Support the major 3rd party providers — facebook, twitter, google and OpenID.
  • Support username/password registration as well.
  • Low barrier to entry — it should work, more or less, out of the box.
  • High customizability: registration becomes a super important part of the new user experience; so the details matter.

To test, I just created a simple app that would consist of nothing but registering, signing in and signing out. I tested each auth app with its own Django 1.3 project, with its dependencies installed in its own virtualenv. To start with, because it’s easier in a test scenario without a registered application, I’m focusing on OpenID. I’m using each package from it’s latest master branch.

Jump to review:

  1. django-socialregistration
  2. Django-Socialauth
  3. django-social-auth
  4. django-allauth

django-socialregistration

Installation

Documented basic steps:

  • Settings:
    • Add socialregistration to INSTALLED_APPS.
    • Add django.core.context_processors.request to TEMPLATE_CONTEXT_PROCESSORS
  • URLs: Add conf for socialregistration.urls, such as:
        url(r'^social/', include('socialregistration.urls')),
  • Templates: No template is provided for login/logout/register, only for the various stages in authenticating with social providers. However, templatetags are provided to easily add forms for the various providers — such as:
    {% load openid_tags %}
    {% openid_form %}

    This needs to be put in a login form somewhere. Logout happens via the normal django auth mechanisms.

Undocumented steps:

  • It relies on the Sites framework to get your site’s URL for callbacks from auth providers. Set the correct site URL in admin.

How it looks

With only an OpenID form and no extra design, it’s pretty plain:

Typing in an OpenID and clicking “Connect with OpenID” sends me to my OpenID provider, and then back to the application to set up Username and Email. So far so good. The template would clearly need to be made a little prettier, but that’s easy to override.

I try typing in a username, and an email address. Uh oh! I get an error.

And not a friendly error at all. “Enter a valid value”? What, pray tell, is valid? It looks like to use this I’ll have to override templates as well as the form class used for setup to put nicer help text in the error message. That means I’ll have to override the URL to the “setup” method in order to pass it a different UserForm class. Let’s try a username without spaces:


Oh no! 500 error. It looks like something’s broken with the OpenID connect code. I dug into this for a while trying to get it to work, but no luck. I filed a bug report here.

Outcome

500 error when trying to connect with OpenID. No dice.


Django-Socialauth

On to the first of the confusingly named Django Social Auth packages.

Installation

Well, the documentation is very thin — this is all they give us:

  1. Install required libraries.
  2. Get tokens and populate in localsettings.py.
  3. Set the token callback urls correctly at Twitter and Facebook.
  4. Set the authentication_backends to the providers you are using.

… ok. Not much help. But there is an example_project directory that gives us some hints.

Undocumented steps:

  • pip install -r /path-to-virtualenv/src/django-socialauth/requirements.txt
  • Settings:
    • Add socialauth and openid_consumer to installed apps.
    • Add socialauth.context_processors.facebook_api_key to TEMPLATE_CONTEXT_PROCESSORS
    • Add openid_consumer.middleware.OpenIDMiddleware to MIDDLEWARE_CLASSES, before the CSRF middleware.
  • URLs:
        url(r'^socialauth/', include('socialauth.urls'))
  • Templates: everything seems to be included by default.

How it looks

Navigating to /socialauth/, we get an OpenID form — makes sense that this is the only one, because I didn’t set up any tokens for Facebook or Twitter.

But when I enter my OpenID and click “Sign-In”, I’m just redirected back to LOGIN_REDIRECT_URL, without being signed in — no indication as to why. I spent a while poking around trying to figure out what was going on, but no dice. Firebug logs requests going out to my OpenID provider and back, but the app seems to just not authenticate. I tried using /socialauth/openid/ as a URL to start the login from, but get a CSRF error.

Outcome

No errors, but the OpenID chain doesn’t result in me being authenticated. It doesn’t work.


django-social-auth

On to the second Django Social Auth package. This one shows more promise — it seems to have more current commits, there’s a solid effort underway to actually add tests (admitedly a difficult thing when dealing with so many external providers and API keys), and it seems designed in a nicely pluggable way for adding other providers in the future. On top of that, it actually has Sphinx docs!

Installation

Documented steps:

  1. Install dependencies. pip has us covered; it already got them when installing the package.
  2. Settings:
    • Add social_auth to INSTALLED_APPS.
    • Add the desired AUTHENTICATION_BACKENDS – there are different ones for each provider. For now, I’m just sticking with social_auth.backens.OpenIDBackend and django.contrib.auth.backends.ModelBackend.
    • Set LOGIN_URL, LOGIN_REDIRECT_URL, and LOGIN_ERROR_URL.
    • Set SOCIAL_AUTH_USERNAME_FIXER to determine the original username that users will get when they register.
  3. URLs:
        url(r'auth/', include('social_auth.urls')),

Undocumented steps:

  • Copy over templates from the included example project to get started, and add some views to use them. The example views are home (a sign in page), done (sign in complete page), and error.

How it looks

Navigating to the home view that I copied over from the example project:

Looks pretty good. I put in my OpenID, confirm at my OpenID provider, and then — oh no!

Strangely, if I repeat the process a second time changing nothing, I am successfuly authenticated. But after logging out, it again takes 2 tries, the first ending in a CSRF failure. I filed a bug and was heartened to get a response from the author within a few hours, though as yet no resolution. But the responsiveness tells me that this project is alive and well and that issues like this probably will get fixed.

Outcome

OpenID ended in a CSRF error. But at least the author responded quickly to a bug report.


django-allauth

django-allauth is the newer kid on the block — first commit was last October. It is also the only one which supports username/password/email registration as well as social registration. It seems like the closest match in spirit to omniauth. It looks like this project was born out of the Pinax mindset, and carries across some pinax-isms into its setup.

Installation

Documented steps:

  • Settings:
        TEMPLATE_CONTEXT_PROCESSORS = (
            ...
            "allauth.context_processors.allauth",
            "allauth.account.context_processors.account"
        )
    
        AUTHENTICATION_BACKENDS = (
            ...
            "allauth.account.auth_backends.AuthenticationBackend",
        )
    
        INSTALLED_APPS = (
            ...
            'emailconfirmation',
            'uni_form',
    
            'allauth',
            'allauth.account',
            'allauth.socialaccount',
            'allauth.twitter',
            'allauth.openid',
            'allauth.facebook',
            ...
        )
  • URLs:
        (r'^accounts/', include('allauth.urls')))

Undocumented steps:

  • A full set of default templates is provided, but these require the presence of site_base.html which contains blocks named head_title and body.
  • Requires django.core.context_processors.request in TEMPLATE_CONTEXT_PROCESSORS (template syntax errors stating that request is undefined are the symptom).
  • If you enable the allauth.facebook and allauth.twitter apps, you have to log into admin and create App entries for them; otherwise you’ll get template errors from template tags that require that they exist.

How it looks

Navigating to /accounts/login/, we get this lovely screen:

Off the bat, google and yahoo authentication work as they should. I don’t have a hyves account so I didn’t test that. Clicking OpenID takes you to this secondary screen:

It looks as though it would be pretty straight-forward to make that load in a nice ajaxy way, or from one page, as well.

And username/password registration works:

Outcome

I’ve gotta say, this one seems like a clear winner. It’s the only one that worked out of the box for me, and it appears to be straight-forward to customize it as needed. The sub-app method of adding providers leads to some slightly hackish noodliness under the hood for things like importing context processors, but it doesn’t look too bad.


Conclusion

django-allauth looks great. django-social-auth looks promising and usable, though I wasn’t able to test as far as I’d like.

All of them need more work with testing and documentation. In part, that’s where we, the developer community come in; but as a maintainer of minor open source projects myself, I know how much its incumbent on the maintainer to buckle down on that stuff if it’s ever going to get done. I’d hazard a guess that some testing and docs for django-allauth or the inclusion of username/password registration on django-social-auth could make one of them a clear winner that we could all put our weight behind. For now, I’m using django-allauth.

This entry was posted in Uncategorized. Bookmark the permalink.

36 Responses to Review of 4 Django Social Auth apps

  1. Leon says:

    Thx for this review! I was doing the same thing and found django_allauth, Django-Socialauth and django-socialregistration.

    I am looking for a django-social-media-app that supports authentication, is easily extendable with other providers, but it should also allow for more than only authentication, like getting profile information and posting messages.

    I like to install one generic social-media app, and maybe install some extensions to be able to connect to extra (more obscure) social media providers. To enable these providers I like to only configure those providers I am using at one place and than I should be able to use them with some simple template tags.

    I haven’t tried them all yet though, but when I was looking at the source code I prefered allauth as well. The code is bundled per social providers, which should make it easy to add new/different providers in the future.

    However, I noticed that Django-Socialauth contains much more functionality than only authenticating, which is something I like to use as well! But the thing I don’t like is that you have to enable an AUTHENTICATION_BACKEND per provider. I like to enable only one generic authentication backend, which should authenticate according to the configured social providers.

    I guess the perfect django-social-app isn’t there yet…

  2. Leon says:

    After some more playing around I think django-social-auth should be the winner 😉

    Its implementation is much better suited to be extended with other authentication backends and all feels much more consistent. In your templates you only have to direct to a url to authenticate with the social network of your choice (no JavaScript requirements) and all profile data from the different providers is stored consistently in one database. It also allows for associating different provider-accounts to one user.

    • From the start the focus of django-allauth has been to deliver an integrated experience and flows that just work, and to a lesser extent a completely pluggable social authentication framework.

      Earlier versions of the project suffered from this, e.g. each provider had its own implementation with its own social account model definition.

      Work is well underway to rectify this situation. These days, social account models have been unified, and adding support for additional OAuth/OAuth2 providers is child’s play.

      Ofcourse, there is always more that can be done. Do know that the biggest hurdles to overcome the initial shortcomings have been taken…

  3. Rami Taibah says:

    I am playing around with django-allauth, however I am having trouble with the first extra requirement. What do you mean by : “hese require the presence of site_base.html which contains blocks named head_title and body?”

  4. @Rami Taibah,
    The templates for django-allauth inherit from a template called “site_base.html”, and use the blocks “head_title” and “body”. This means that unless you have a template somewhere that is named “site_base.html” which contains blocks named “head_title” and “body”, you will see nothing, or get a template error.
    A minmal “site_base” template might look like:


    <html>
    <head>
    <title>
    {% block head_title %}{% endblock %}
    </title>
    </head>
    <body>
    {% block body %}{% endblock %}
    </body>
    </html>

  5. avnc says:

    @HackerLuddite: Thanks for the nice review. Also thanks to @Leon for some very informative comments.

    Was just wondering how your decision to go with django-allauth has worked for you in the last couple of months. Do you still like it after spending more time with it? Does it fall short of any of your requirements? Any deal breaking bugs/feature omissions?

    It’d be very helpful if you could share your experience.

    -avnc

  6. Leon says:

    hello avnc,

    I can tell you that I continued working with django-social-auth (please note the indent between social and auth ;)) and am still very pleased with it.

    I can enable and disable any authentication provider,
    write my own authentication provider (if I want),
    have full control over the templates (and for instance make only the enabled providers show up to allow login),
    associated multiple social-logins to one django-account,
    get profile information during login (inc. urls to avatars)

    and last but not least:
    use the returned authentication token in different parts of my application to make use of different specialised libraries, for instance to resolve the full linkedin profile or post to facebook, etc.

    An Example:

    
    def _getLinkedInProfile(user):
        """Get the associated LinkedIn Profile, or raise an Exception, when not logged in, or
        no LinkedIn account is associated"""
        if not hasattr(user, 'social_auth') or not user.social_auth.filter(provider='linkedin'):
            raise NoLinkedInAccountException('No associated LinkedIn profile found')
    
        linkedin_sa = user.social_auth.get(provider='linkedin')
        access_token = Token.from_string(linkedin_sa.extra_data['access_token'])
    
        api = linkedin.LinkedIn(settings.LINKEDIN_CONSUMER_KEY, settings.LINKEDIN_CONSUMER_SECRET, '')
        api.access_token = access_token.key
        api.access_token_secret = access_token.secret
    
        profile = api.GetProfile(fields=[
                'id',
                'first-name',
                'last-name',
                ....
                'picture-url',
                'site-public-profile-request:(url)',
        ])
    
        return profile
    
  7. @avnc, after doing this research, I have still not deployed a django-allauth site (have been hammered in other sides of the development). I’ll definitely post an update when I get there. In the mean time I’m pleased to see others’ posts of their experiences.

  8. avnc says:

    Thank Leon and hackerluddite for your responses. I think I’ll give django-social-auth a spin before trying out others. Judging by Leon’s response, I should not have to look any further.

  9. Leon says:

    Goodluck avnc and please let me/us know what you think of it.
    If you’ve got any questions feel free to ask me.

  10. Alejandro says:

    Thanks a lot for this post!

  11. Pingback: django-social-auth: Installing and troubleshooting « William John Bert

  12. Matias says:

    As django-social-auth developer, I found this post very informative and with good criticism.

    Thanks,
    Matías

    BTW: after a lot of digging the mentioned bug was fixed.

  13. Great post, but the all mentioned projects still in development (heavy), and some bugs have been fixed (good point).

    Stills hard to decide what app use and I am thinking with myself: There will be a day that we, pythonists/djangonauts will have a killer packege like omniauth?

  14. Martin says:

    Hey there,

    great post – thanks! I’ve tried all of the above mentioned packages, too, with similar requirements in mind as you posted. In the end, I’m not using social-auth together with a small app extracted from allauth to allow for standard registration/login/password change. The extraction of that part was fairly straight forward, it’s the parts stored in allauth/account with hardly any dependencies on the actual allauth package.

    If you’re interested, I am happy to post you that app. To me this seemed to be the easiest way to combine the power of social-auth with the advantages of allauth into a single product.

    • Tom says:

      Martin – I’m just about to try integrating social-auth into an existing site which already has username/password authentication. If you could post me the app (assuming this comment system allows you to view my email address), or better still reply with a publicly accessible link, I would be very very grateful.

  15. Clear and concise. Love it. Keep up the good work.

  16. Allan Deamon says:

    Thks. Wonderful. Saved a lot of my time. Thank you again.

  17. Pingback: BernardoFontes.net » Blog Archive » Autenticando o seu usuário Django pelo Facebook

  18. Aris says:

    I’m exploring the same set of social authentication options. It’s very frustrating because it seems as if most people have made their choice and stuck with it instead of comparing to the other popular modules. Have you checked in on any of the packages in the past year? I posted a question on StackOverflow about this two days ago and I’m still waiting for replies: http://stackoverflow.com/questions/11065303/comparison-of-django-social-media-authentication-modules

  19. Rob B says:

    Thanks for the post. I can also confirm that django-allauth is indeed the easiest to setup. Had it working in 5min after trying to get django-social-auth to work for hours. Only tried them with Twitter auth so far.

  20. so far, I installed django-allauth and it works very good, not like django-userena ¬¬. However, I was wondering about extending User model. Extending it will affect django-allauth in some way?

  21. Pingback: Integrating Linkedin OAuth with an existing django app | Stafftacular

  22. Pingback: Johnny Brown » Integrating Linkedin OAuth with an existing django app

  23. Chris Young says:

    Thankyou x 100 for calling out the undocumented steps. You saved me hours of frustration!

  24. peneves says:

    BTW, django-social-auth has been deprecated in favor of python-social-auth http://psa.matiasaguirre.net/docs/index.html

    The new package documentation looks more confusing than the older one. There’s no “quick setup”. At least there is an option for configuring email authentication.

    Unfortunately I’ve found your page just after spending all my afternoon trying to configure it.

  25. peneves says:

    +1 for django-allauth

    I’ve spent my afternoon trying to configure python-social-auth and failed. In less time than I’ve spent to write an email to their mailling list asking for instructions, I’ve configured allauth

  26. brycenesbitt says:

    Note: The author of django-allauth offers professional services for install, in case you don’t want to mess with it.

  27. jpatel3 says:

    django-social-auth is been merged with python-social-auth(https://github.com/omab/python-social-auth)

  28. yashwanth says:

    I have a query in django-social-auth.
    After logging in using facebook, twitter whatever it may be. It will take the details of the user like username, email, fullname, lastname into the django admin users list.
    I have my django registration form in separate. In that while clicking the forgot password, it will ask for the email for sending the password reset link.
    My query was the email was not sending for the emails which have been taken for the social users.

    Please provide useful info for this. Thanks 🙂

  29. Pingback: Python:Which solution is better for Django social authentication? – IT Sprite

Leave a comment